그래프 탐색 알고리즘(BFS,DFS)
그래프 탐색
하나의 정점에서 시작해서 모든 정점을 한번씩 방문하는 작업을 말한다.
그래프 문제들 중 다수는 단순히 정점들의 탐색만으로 해결되기도 한다.
탐색은 정점과 인접한 저점들 중에서 아직 방문하지 않은 정점으로만 가능하다
→ visited등으로 방문한 정점을 관리한다
graph={"A":{"B","C"},
"B":{"D"},
"C":{"G","H","I"},
"D":{"E","F"},
"I":{"J"},
}
연결리스트를 이용한 방식을 기준으로 작성했다.
DFS(depth firsth search)
정점의 자식들을 먼저 탐색하는 방식이다.
재귀 혹은 stack을 사용해서 구현한다.
재귀를 이용한 구현
def dfs(graph, start, visited,path):
visited.append(start)
print(start, end=" ")
for i in graph[start]:
if i not in visited:
dfs(graph, i, visited)
stack을 이용한 구현
def dfs(graph, start, visited):
stack = [start]
while stack:
v = stack.pop()
if v not in visited:
visited.append(v)
stack.extend(graph[v])
시간 복잡도
- 노드수가 v, 간선의 수가 e
- 인접행렬
- 모든 배열을 돌면서 연결정보를 확인해야하기 때문에 O(
)
- 모든 배열을 돌면서 연결정보를 확인해야하기 때문에 O(
- 인접 리스트
- O(
)
- O(
최대 간선의 수는 v(v-1)가 된다.
⇒ 대부분의 경우에 dfs 인접 리스트의 사용이 인접 행렬보다 시간적으로 유리하다.
BFS(breadth first search)
queue를 사용해서 구현한다.
def bfs(graph,start,visited):
queue = [start]
while queue:
v = queue.pop(0)
if v not in visited:
visited.append(v)
queue.extend(graph[v])
시간복잡도
bfs와 동일하다.
→ 인접리스트를 사용하는 것이 효율적이다
BFS, DFS 선택 기준
그래프 탐색이 필요한 문제는 DFS와 BFS 모두 이용해서 풀 수 있지만, 어떤 방법을 선택하느냐에 따라서 결과가 좌우되는 문제도 있다.
그러면 어떤 기준으로 BFS 와 DFS 중 한가지 방법을 선택할 수 있을 까?
DFS
- 먼저 노드의 끝, 목적지에 도달하므로 검색 대상의 그래프가 커도 목적지까지는 BFS보다 먼저 도달할 수 있다.
- 경로의 특징을 가질 수 있다. → 경로에 대한 정보가 있는 문제에서 활용할 수 있다.
BFS
- 최단 경로를 찾는데 유용하다.
- DFS를 통해서 처음 발견되는 해답이 최단 거리를 보장해주지 못하므로 BFS사용하는 것이 유리하다. BFS는 첫번째로 찾아지는 해답이 곧 최단거리이다. → BFS에서는 모두 같은 단계로 탐색하니까.